﻿using System;
using System.Collections.Specialized;
using System.Windows.Forms;
using VkApiVer2.api.Utils;
using VkApiVer2.extensions;
using WebKit;

namespace VkApiVer2.api
{
    public class ClientAuthorization
    {

        private Uri RedirectUri { get; set; }
        private string DisplayType { get; set; }
        private AuthForm AuthForm = new AuthForm();
        private WebKitBrowser Browser { get; set; }
        public string ApplicationId { get; set; }
        public String Scope { get; set; }
        public delegate void ResultHander(object sender, Result result);
        public event ResultHander ResultEvent;
        public Form ParentForm { private get; set; }
        public Result Result { get; private set; }

        public enum Access
        {
            Allow = 1,
            Deny = 0
        }
        public enum Display
        {
            wap, popup
        }

        private const string AccessTokenParameter = "access_token";
        private const string ExpireInParameter = "expires_in";
        private const string UserIdParameter = "user_id";
        private const string ErrorParameter = "error";
        private const string AuthHost = "oauth.vkontakte.ru";
        private const string AuthPath = "authorize";
        private const string PopupWindow = "popup";
        private const string WapWindow = "wap";
        private const string RedirectUriString = "http://oauth.vk.com/blank.html";


        public ClientAuthorization(string applicationId, String scope, Display displayType)
            : this(applicationId, displayType)
        {
            Scope = scope;
        }
        public ClientAuthorization(string applicationId, Display displayType)
        {
            ApplicationId = applicationId;
            DisplayType = GetDisplayTypeString(displayType);
            Scope = RightsUtils.GetMaxRights();
            RedirectUri = new Uri(RedirectUriString);

        }

        private string GetDisplayTypeString(Display displayType)
        {
            switch(displayType)
            {
                case Display.wap:
                    return WapWindow;
                case Display.popup:
                    return PopupWindow;
                default:
                    return PopupWindow;
            }
        }

        private Uri GetAuthUri()
        {
            var uriBuilder = new UriBuilder { Host = AuthHost, Path = AuthPath };
            var query = new QueryString();
            var parameters = new NameValueCollection
            {
            {"client_id",ApplicationId},
            {"scope",Scope},
            {"redirect_uri",RedirectUri.ToString()},
            {"display",DisplayType},
            {"response_type","token"}
            };
            query.Add(parameters);
            uriBuilder.Query = MyExtensions.ConstructQueryString(query);
#if DEBUG
            Console.WriteLine(uriBuilder.Uri);
#endif
            return uriBuilder.Uri;
        }

        public void Auth()
        {
            Browser = AuthForm.webKitBrowser1;
            Browser.Navigate(GetAuthUri().ToString());
            Browser.Navigated += Browser_Navigated;
            Browser.DocumentCompleted += Browser_DocumentCompleted;
            if(ParentForm != null)
                ParentForm.Enabled = false;
            AuthForm.Show();

        }

        void Browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            Result = new Result();
            var kitBrowser = sender as WebKitBrowser;
            if(kitBrowser != null && kitBrowser.DocumentText.Equals("security breach"))
            {
                Result.Access = Access.Deny;
                Result.ErrorDescription = "Security breach";
                AuthForm.Hide();
                if(ParentForm != null)
                {
                    ParentForm.Enabled = true;
                }
                ResultEvent(this, Result);
            }
            else
            {
                if(e.Url.Equals(RedirectUri))
                {
                    //#access_token=8a7abe32c4c72a418b9a041b9c8b0b244988b258b385d8f21bc90645c9ad2b9&expires_in=86400&user_id=22830147
                    if(e.Url.Fragment.Substring(1, AccessTokenParameter.Length).Equals(AccessTokenParameter))
                    {
                        //access_token=8a7abe32c4c72a418b9a041b9c8b0b244988b258b385d8f21bc90645c9ad2b9&expires_in=86400&user_id=22830147
                        var queryString = new QueryString(e.Url.Fragment.Substring(1));
                        Result.AccessToken = queryString[AccessTokenParameter];
                        var seconds = Convert.ToDouble(queryString[ExpireInParameter]);
                        Result.Expire = seconds.Equals(0) ? DateTime.Now.AddYears(1) : DateTime.Now.AddSeconds(seconds);

                        Result.UserId = queryString[UserIdParameter];

                        Result.Access = Access.Allow;
                    }
                    else
                    {
                        if(e.Url.Fragment.Substring(1, ErrorParameter.Length).Equals(ErrorParameter))
                        {
                            var query = e.Url.Fragment.Substring(1);
                            var queryString = new QueryString(query);
                            Result.Error = queryString["error"];
                            Result.ErrorReason = queryString["error_reason"];
                            Result.ErrorDescription = queryString["error_description"];
                            Result.Access = Access.Deny;
                        }
                    }
                    AuthForm.Hide();
                    if(ParentForm != null)
                    {
                        ParentForm.Enabled = true;
                    }
                    ResultEvent(this, Result);
                }
            }

        }

        void Browser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
        {
            Console.WriteLine(e.Url);
        }
    }

    public class Result
    {
        public string AccessToken { get; set; }
        public string Error { get; set; }
        public string ErrorReason { get; set; }
        public string ErrorDescription { get; set; }
        public DateTime Expire { get; set; }
        public string UserId { get; set; }
        public ClientAuthorization.Access Access { get; set; }

        public Result()
        {
            Access = ClientAuthorization.Access.Deny;

        }
    }
}


